package com.acme.chat.client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

import com.acme.chat.message.ChatMessage;
import com.acme.chat.message.Message;
import com.acme.chat.message.MessageType;
import com.acme.chat.server.Server;

public class Client implements ChatClient {

    private ObjectInputStream sInput;
    private ObjectOutputStream sOutput;
    private Socket socket;
    private ClientGUI clientGUI;
    private String server;
    private String name;
    private int port;
    private String room;

    public Client(String server, int port, String room, String username) {
        this(server, port, room, username, null);
    }

    public Client(String server, int port, String room, String name, ClientGUI cg) {
        this.server = server;
        this.port = port;
        this.room = room;
        this.name = name;
        this.clientGUI = cg;
    }

    public boolean start() {
        try {
            socket = new Socket(server, port);
        } catch (Exception ec) {
            display("Error connectiong to server:" + ec);
            return false;
        }

        String msg = "Connection accepted " + socket.getInetAddress() + ":" + socket.getPort();
        msg = msg + ", room: " + room;
        display(msg);

        try {
            sInput = new ObjectInputStream(socket.getInputStream());
            sOutput = new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException eIO) {
            display("Exception creating new Input/output Streams: " + eIO);
            return false;
        }

        try {
            sOutput.writeObject(name);
            sOutput.writeObject(room);
        } catch (IOException e) {
            display("Exception doing login : " + e);
            disconnect();
            return false;
        }
        new ListenFromServer().start();
        return true;
    }

    private void display(String msg) {
        if (clientGUI == null) {
            System.out.println(msg);
        } else {
            clientGUI.append(msg + "\n");
        }
    }

    public boolean sendMessage(Message message) {  //or public or delete from interface ChatClient
        try {
            if (message.getMessage().length() > Message.MAX_MESSAGE_LENGTH) {
                throw new IllegalArgumentException("Message is too long! Max allowed message size is " + Message.MAX_MESSAGE_LENGTH + " symbols.\n");

            }
            sOutput.writeObject(message);
            return true;
        } catch (IOException e) {
            display("Exception writing to server: " + e);
            return false;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return false;
        }
    }

    public void disconnect() {
        try {
            if (sInput != null) {
                sInput.close();
            }
        } catch (Exception e) {
        }
        try {
            if (sOutput != null) {
                sOutput.close();
            }
        } catch (Exception e) {
        }
        try {
            if (socket != null) {
                socket.close();
            }
        } catch (Exception e) {
        }
        if (clientGUI != null) {
            clientGUI.connectionFailed();
        }

    }

    public String getRoom() {
        return room;
    }

    public String getName() {
        return name;
    }

    private class ListenFromServer extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    Message message = (Message) sInput.readObject();
                    if (clientGUI == null) {
                        System.out.println(message.getMessage());
                        System.out.print("> ");
                    } else {
                        clientGUI.append(message.getMessage());
                    }
                } catch (IOException e) {
                    display("Server has close the connection: " + e);
                    if (clientGUI != null) {
                        clientGUI.connectionFailed();
                    }
                    break;
                } catch (ClassNotFoundException e2) {
                }
            }
        }
    }

    public static void main(String[] args) {
        int portNumber = 1500;
        String roomNumber = "1";
        String serverAddress = "localhost";
        String userName = "Anonymous";

        switch (args.length) {
            case 4:
                roomNumber = args[3];
            case 3:
                serverAddress = args[2];
            case 2:
                try {
                    portNumber = Integer.parseInt(args[1]);
                } catch (Exception e) {
                    System.out.println("Invalid port number.");
                    System.out.println("Usage is: > java Client [username] [portNumber] [serverAddress]");
                    return;
                }
            case 1:
                userName = args[0];
            case 0:
                break;
            default:
                System.out.println("Usage is: > java Client [username] [portNumber] [roomNumber] [serverAddress] ");
                return;
        }
        Client client = new Client(serverAddress, portNumber, roomNumber, userName);
        if (!client.start()) {
            return;
        }
        Scanner scan = new Scanner(System.in);
        while (true) {
            System.out.print("> ");
            String msg = scan.nextLine();
            if (msg.equalsIgnoreCase("LOGOUT")) {
                client.sendMessage(new ChatMessage(MessageType.LOGOUT, ""));
                break;
            } else if (msg.equalsIgnoreCase("WHOISIN")) {
                client.sendMessage(new ChatMessage(MessageType.WHOISIN, ""));
            } else {
                client.sendMessage(new ChatMessage(MessageType.MESSAGE, msg));
            }
        }
        client.disconnect();
    }

    public void connect(Server server) {

    }

    public void incomingMessage(Message message) {

    }

    public boolean isConnected() {
        return false;
    }

    public void addListener(ClientListener listener) {
        // TODO Auto-generated method stub

    }
}